package com.gxar.marketdelivery.shared.utils;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.gxar.marketdelivery.domain.aviator.model.PatternWithMessageFormat;
import com.gxar.marketdelivery.interfaces.web.result.IResponseStatusMsg;
import com.gxar.marketdelivery.shared.consts.Separator;
import com.gxar.marketdelivery.shared.meta.exception.APIRuntimeException;
import com.networknt.schema.JsonMetaSchema;
import com.networknt.schema.JsonSchema;
import com.networknt.schema.JsonSchemaFactory;
import com.networknt.schema.SpecVersion;
import com.networknt.schema.ValidationMessage;

import java.io.IOException;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author nice
 * @version 1.0
 * @created 2023/7/21.
 */
public class JsonSchemaUtil {

    private static final JsonSchemaFactory schemaFactory;

    static {
        JsonMetaSchema.COMMON_BUILTIN_FORMATS.add(new PatternWithMessageFormat("color",
                "(#([0-9A-Fa-f]{3,6})\\b)|(aqua)|(black)|(blue)|(fuchsia)|(gray)|(green)|(lime)|(maroon)|(navy)|(olive)|(orange)|(purple)|(red)|(silver)|(teal)|(white)|(yellow)|(rgb\\(\\s*\\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\b\\s*,\\s*\\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\b\\s*,\\s*\\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\b\\s*\\))|(rgb\\(\\s*(\\d?\\d%|100%)+\\s*,\\s*(\\d?\\d%|100%)+\\s*,\\s*(\\d?\\d%|100%)+\\s*\\))",
                "颜色配置不正确,格式示例:#3F3F3F"));
        schemaFactory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V201909);
    }

    private static final ObjectMapper objectMapper = new ObjectMapper();

    public static <T> T parseJson(String schemaValueJson) {
        try {
            return (T) objectMapper.readTree(schemaValueJson);
        } catch (IOException e) {
            e.printStackTrace();
            throw new APIRuntimeException(IResponseStatusMsg.APIEnum.PARAM_ERROR, "Json 解析失败");
        }
    }

    public static ObjectNode createObjectNode() {
        return objectMapper.createObjectNode();
    }

    public static ArrayNode createArrayNode() {
        return objectMapper.createArrayNode();
    }

    public static void validate(String schemaDefinition, JsonNode jsonNode) {
        AssertUtils.notNull(schemaDefinition, IResponseStatusMsg.APIEnum.PARAM_ERROR, "schema不能为空");
        AssertUtils.notNull(jsonNode, IResponseStatusMsg.APIEnum.PARAM_ERROR, "jsonNode不能为空");
        JsonSchema jsonSchema = schemaFactory.getSchema(schemaDefinition);
        Set<ValidationMessage> errors = jsonSchema.validate(jsonNode);
        if (CollectionUtils.isNotEmpty(errors)) {
            String errorMessage = errors.stream().map(ValidationMessage::getMessage)
                    .collect(Collectors.joining(Separator.COMMA));
            throw new APIRuntimeException(IResponseStatusMsg.APIEnum.PARAM_ERROR, errorMessage);
        }
    }

    public static void validate(JsonSchema schema, String schemaValueJson) {
        AssertUtils.notNull(schema, IResponseStatusMsg.APIEnum.PARAM_ERROR, "schema不能为空");
        AssertUtils.notNull(schemaValueJson, IResponseStatusMsg.APIEnum.PARAM_ERROR, "jsonNode不能为空");
        JsonNode jsonNode = parseJson(schemaValueJson);
        Set<ValidationMessage> errors = schema.validate(jsonNode);
        if (CollectionUtils.isNotEmpty(errors)) {
            String errorMessage = errors.stream().map(ValidationMessage::getMessage)
                    .collect(Collectors.joining(Separator.COMMA));
            throw new APIRuntimeException(IResponseStatusMsg.APIEnum.PARAM_ERROR, errorMessage);
        }
    }
}
